// 2025/10/11: 首个版本

using System;
using System.Collections.ObjectModel;
using System.Xml;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using Avalonia.Interactivity;
using Avalonia.Platform.Storage;
using ASEva;
using ASEva.Utility;
using ASEva.UIAvalonia;

namespace CommonSource
{
    partial class SessionDefaultProperties : DialogPanel
    {
        public SessionDefaultProperties()
        {
            InitializeComponent();
            SetResizableMode(430, 270, 430, 270);
            language = new LanguageSwitch(Resources, AgencyLocal.GetAppLanguage());
            Title = language["title"];
            DataContext = model;

            buttonAdd.Click += buttonAdd_Click;
            buttonRemove.Click += buttonRemove_Click;
            buttonExport.Click += buttonExport_Click;
            buttonImport.Click += buttonImport_Click;
            buttonOK.Click += buttonOK_Click;

            if (FuncManager.Run("System.GetDesignerModeFlag") == null)
            {
                initialize();
            }
        }

        public String IconResourceName
        {
            set => Icon = ResourceLoader.Load(value)?.ToAvaloniaWindowIcon();
        }

        private void buttonAdd_Click(object sender, RoutedEventArgs args)
        {
            model.TableItems.Add(new PropertyItem("", ""));
        }

        private void buttonRemove_Click(object sender, RoutedEventArgs args)
        {
            if (tableView.SelectedIndex >= 0) model.TableItems.RemoveAt(tableView.SelectedIndex);
        }

        private async void buttonExport_Click(object sender, RoutedEventArgs args)
        {
            var xml = await export(true);
            if (xml == null) return;

            var result = await this.GetStorageProvider().SaveFilePickerAsync(new FilePickerSaveOptions
            {
                DefaultExtension = ".asmc",
                FileTypeChoices = [ new FilePickerFileType(language["module-config"]){ Patterns = ["*.asmc"] } ],
            });
            if (result == null) return;

            xml.Save(result.Path.LocalPath);
        }

        private async void buttonImport_Click(object sender, RoutedEventArgs args)
        {
            var result = await this.GetStorageProvider().OpenFilePickerAsync(new FilePickerOpenOptions
            {
                FileTypeFilter = [ new FilePickerFileType(language["module-config"]){ Patterns = ["*.asmc" ] } ],
            });
            if (result.Count == 0) return;

            var xml = new XmlDocument();
            try { xml.Load(result[0].Path.LocalPath); }
            catch (Exception)
            {
                await AgencyLocal.PopupError(language["failed-load-xml"]);
                return;
            }

            await import(xml, true);
        }

        private async void buttonOK_Click(object sender, RoutedEventArgs args)
        {
            var xml = await export(false);
            if (xml == null) return;

            await AgencyAsync.SetGlobalParameter("System.SessionDefaultProperties", xml.InnerXml);

            Close();
        }

        private async void initialize()
        {
            this.IsEnabled = false;

            var xmlString = await AgencyAsync.GetGlobalParameter("System.SessionDefaultProperties", null);
            if (xmlString == null) return;

            var xml = new XmlDocument();
            try { xml.LoadXml(xmlString); }
            catch (Exception) { return; }

            await import(xml, false);

            this.IsEnabled = true;
        }

        private async Task import(XmlDocument xml, bool asmc)
        {
            if (asmc)
            {
                var typeAttrib = xml.DocumentElement.Attributes["type"];
                if (typeAttrib == null || typeAttrib.Value != "property-preset")
                {
                    await AgencyLocal.PopupError(language["failed-asmc-type"]);
                    return;
                }
            }

            foreach (XmlElement propertyNode in xml.DocumentElement.GetElementsByTagName("property"))
            {
                var attribs = propertyNode.Attributes;
                if (attribs["key"] == null || attribs["value"] == null) continue;
                model.TableItems.Add(new PropertyItem(attribs["key"].Value, attribs["value"].Value));
            }
        }

        private async Task<XmlDocument> export(bool asmc)
        {
            var xml = Xml.Create("root");
            var rootNode = xml.DocumentElement;

            if (asmc) rootNode.Attributes.Append(xml.CreateAttribute("type")).Value = "property-preset";

            var keyFlags = new Dictionary<String, bool>();
            var duplicatedFlags = new Dictionary<String, bool>();
            foreach (var item in model.TableItems)
            {
                if (String.IsNullOrWhiteSpace(item.Key)) continue;

                if (keyFlags.ContainsKey(item.Key))
                {
                    duplicatedFlags[item.Key] = true;
                    continue;
                }
                else keyFlags[item.Key] = true;

                var attribs = rootNode.AppendChild(xml.CreateElement("property")).Attributes;
                attribs.Append(xml.CreateAttribute("key")).Value = item.Key;
                attribs.Append(xml.CreateAttribute("value")).Value = item.Value;
            }

            var duplicatedKeys = duplicatedFlags.Keys.ToArray();
            if (duplicatedKeys.Length > 0)
            {
                await AgencyLocal.PopupError(language["duplicated"] + "\n" + String.Join('\n', duplicatedKeys));
                return null;
            }

            return xml;
        }

        partial class PropertyItem(String _key, String _value) : ObservableObject
        {
            [ObservableProperty]
            private String key = _key;

            [ObservableProperty]
            private String value = _value;
        }

        partial class Model : ObservableObject
        {
            [ObservableProperty]
            private ObservableCollection<PropertyItem> tableItems = new();
        }

        private Model model = new();
        private LanguageSwitch language;
    }
}